import networkx as nx
from mininet.topo import Topo
from mininet.net import Mininet
from mininet.node import OVSBridge, Controller, Node,OVSSwitch,findController

from optparse import OptionParser
from mininet.log import setLogLevel
from mininet.cli import CLI
import time
from ipgen import IpGen
from plot import cdf, scatter,hist
import os


class LinuxRouter(Node):
    "A Node with IP forwarding enabled."

    def config(self, **params):
        super(LinuxRouter, self).config(**params)
        # Enable forwarding on the router
        self.cmd('sysctl net.ipv4.ip_forward=1')
        # self.cmd('socat tcp-l:2620,fork,reuseaddr tcp:11.0.0.254:2620 &')

    def terminate(self):
        self.cmd('sysctl net.ipv4.ip_forward=0')
        self.cmd('pkill zebra')
        self.cmd('pkill ospf')
        super(LinuxRouter, self).terminate()

class Mycli(CLI, object):
    def __init__(self, net):
        super(Mycli, self).__init__(net)

    def do_init_ospf(self, line):
        with open('log', 'a') as f:
            f.write('==== init ====\n')
        for node in self.mn.topo.nodes():
            if 'h' in node:
                continue
            self.mn.get(node).cmd('/home/gd/frr/zebra/zebra -i /tmp/zebra-%s.pid -f r1/zebra.conf -N %s -M fpm:protobuf -d' % (node, node))
            self.mn.get(node).cmd('/home/gd/frr/ospfd/ospfd -i /tmp/ospfd-%s.pid -f r1/ospfd.conf -N %s -d' % (node, node))

    def do_batchlink(self, line):
        arr = line.split()

        with open('log', 'a') as f:
            f.write('==== batch %s ====\n' % line)

        for c in open(arr[0]):
            super(Mycli, self).do_link(c)
            

    def do_link(self, line):
        str = line
        arr = line.split()
        if len(arr) > 3:
            str = ' '.join(arr[0:3])
        with open('log', 'a') as f:
            f.write('==== link %s ====\n' % line)
        super(Mycli, self).do_link(str)
    
    def do_draw(self, line):
        arr = line.split(maxsplit=1)
        if arr[0] == 'scatter':
            scatter('log', arr[1])
        elif arr[0] == 'cdf':
            cdf('log', arr[1])
        elif 'hist' in arr[0]:
            bins = 1
            if len(arr[0]) > 4:
                bins = int(arr[0].split('t')[1])
            hist('log', arr[1], bins)
        
    def do_test(self, line):
        print(line)


def sim(g: nx.Graph):
    gwMap = {}
    topo = Topo()
    c = topo.addHost('c', ip='11.254.254.254/8')
    s0 = topo.addSwitch('s0', cls=OVSBridge)
    topo.addLink(c, s0)

    for n in g.nodes:
        if 'h' in n:
            topo.addHost(n, ip=None)
        else:
            topo.addNode(n, cls=LinuxRouter, ip=None)
            topo.addLink(s0, n, params2={'ip': IpGen().genCIP()})
            
    for l in g.edges:
        if 'h' in l[0] or 'h' in l[1]:
            ips = IpGen().genHIP()
            topo.addLink(l[0], l[1], params1={'ip': ips[0]}, params2={'ip': ips[1]})
            if 'h' in l[0]:
                gwMap[l[0]] = ips[1]
            if 'h' in l[1]:
                gwMap[l[1]] = ips[0]
        else:
            ips = IpGen().gen()
            topo.addLink(l[0], l[1], params1={'ip': ips[0]}, params2={'ip': ips[1]})

    # setLogLevel('info')
    net = Mininet(topo=topo, controller=None)
    net.start()
    
    for (k, v) in gwMap.items():
        net.get(k).cmd('route add default gw %s' % v.split('/')[0])
    Mycli(net)
    net.stop()
    os.system('pkill ospfd')
    os.system('pkill zebra')


